{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3068c6e9",
   "metadata": {},
   "source": [
    "### RNA 逆转录 Baseline (Based on RDesign)\n",
    "This code establishes a baseline for ​RNA inverse folding​ (sequence design from structure), adapted from [A4Bio/RDesign](https://github.com/A4Bio/RDesign). It processes RNA structural coordinates (.npy files) paired with sequences (FASTA), splits data into train/valid/test sets, and creates PyTorch datasets where inputs are 3D backbone coordinates (P, C4', O3' atoms) and targets are corresponding RNA sequences. \n",
    "\n",
    "RNA有四种碱基：AGCU, adenine（腺嘌呤）、 Uracil（尿嘧啶）, Cytosine（胞嘧啶）和 Guanine（鸟嘌呤）\n",
    "\n",
    "RNA的序列结构：\n",
    "\n",
    "            碱基                碱基                 碱基\n",
    "磷酸基团-五碳糖(核糖)-磷酸基团-五碳糖(核糖)-磷酸基团-五碳糖(核糖)\n",
    "\n",
    "\n",
    "```text\n",
    "主链方向：C5' → C3'\n",
    "  ...-P-O5'–C5'–C4'–C3'–O3'-P-...\n",
    "            |     \n",
    "            C1'  \n",
    "            / \\ \n",
    "            碱基\n",
    "核糖(5碳糖)主链原子（O5'-C5'-C4'-C3'-O3'），磷酸基团P，碱基N1/N9\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a1a25400",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install torch, pandas, biopython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "159f7029-9f98-48b1-aa8f-d3ab43894deb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "import random\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import torch.nn as nn\n",
    "from tqdm import tqdm\n",
    "from typing import List, Dict\n",
    "from torch.optim import Adam\n",
    "import torch.nn.functional as F\n",
    "from torch.utils.data import Dataset\n",
    "from torch.utils.data import DataLoader\n",
    "from dataclasses import dataclass, field\n",
    "from torch_scatter import scatter_sum, scatter_softmax\n",
    "from Bio import SeqIO  # pip install biopython\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1faeb703",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/workspace/sais_medicine\n"
     ]
    }
   ],
   "source": [
    "# Define Configuration Classes\n",
    "root_dir = os.path.dirname(os.getcwd())\n",
    "print(root_dir)\n",
    "datapath = 'saistraindata'\n",
    "datapath = 'saisdata'\n",
    "@dataclass\n",
    "class DataConfig:\n",
    "    datapath: str = f'{root_dir}/{datapath}'  # 数据根目录\n",
    "    fasta_data_path: str = f'{datapath}/seqs'  # 标签数据\n",
    "    coords_data_path: str = f'{datapath}/coords'  # 特征数据\n",
    "    outputs_path: str = f'{root_dir}/outputs'\n",
    "    \n",
    "    train_npy_data_dir: str = f'{datapath}/coords'\n",
    "    valid_npy_data_dir: str = f'{datapath}/coords'\n",
    "    test_npy_data_dir: str = f'{datapath}/coords'\n",
    "    \n",
    "    train_data_path: str = f'{root_dir}/outputs/public_train_data.csv'\n",
    "    valid_data_path: str = f'{root_dir}/outputs/public_valid_data.csv'\n",
    "    test_data_path: str = f'{root_dir}/outputs/public_test_data.csv'\n",
    "\n",
    "@dataclass\n",
    "class ModelConfig:\n",
    "    smoothing: float = 0.1\n",
    "    hidden: int = 128\n",
    "    vocab_size: int = 4  # 明确指定为 int 类型\n",
    "    k_neighbors: int = 30  # 明确指定为 int 类型\n",
    "    dropout: float = 0.1\n",
    "    node_feat_types: List[str] = field(default_factory=lambda: ['angle', 'distance', 'direction'])  # 使用 field 避免可变对象问题\n",
    "    edge_feat_types: List[str] = field(default_factory=lambda: ['orientation', 'distance', 'direction'])  # 同上\n",
    "    num_encoder_layers: int = 3\n",
    "    num_decoder_layers: int = 3  # 修正为整数，去掉多余的小数点\n",
    "\n",
    "@dataclass\n",
    "class TrainConfig:\n",
    "    batch_size: int = 8\n",
    "    epoch: int = 10\n",
    "    lr: float = 0.001\n",
    "    output_dir: str = f'{root_dir}/code/weights'\n",
    "    ckpt_path: str = f'{root_dir}/code/weights/best.pt'\n",
    "\n",
    "@dataclass\n",
    "class Config:\n",
    "    pipeline: str = 'train'\n",
    "    seed: int = 2025\n",
    "    device: str = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
    "    data_config: DataConfig = DataConfig()\n",
    "    model_config: ModelConfig = ModelConfig()\n",
    "    train_config: TrainConfig = TrainConfig()\n",
    "    seq_vocab: str = \"AUCG\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6c9a137",
   "metadata": {},
   "source": [
    "### Data processing\n",
    "This code implements an RNA data processing pipeline for machine learning tasks using PyTorch and Biopython."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "a6c2f4ec-4be4-4b8f-a0c6-d213ca157a86",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 2317/2317 [00:00<00:00, 26935.82it/s]\n"
     ]
    }
   ],
   "source": [
    "# Define function to read FASTA files using Biopython\n",
    "def read_fasta_biopython(file_path):\n",
    "    sequences = {}\n",
    "    for record in SeqIO.parse(file_path, \"fasta\"):\n",
    "        sequences[record.id] = str(record.seq)\n",
    "    return sequences\n",
    "\n",
    "# 读取FASTA文件，即标签\n",
    "train_file_list = os.listdir(DataConfig.fasta_data_path)\n",
    "content_dict = {\n",
    "    \"pdb_id\": [],\n",
    "    \"seq\": []\n",
    "}\n",
    "for file in tqdm(train_file_list):\n",
    "    data_path = os.path.join(DataConfig.fasta_data_path, file)\n",
    "    sequences = read_fasta_biopython(data_path)\n",
    "    content_dict[\"pdb_id\"].append(list(sequences.keys())[0])\n",
    "    content_dict[\"seq\"].append(list(sequences.values())[0])\n",
    "\n",
    "data = pd.DataFrame(content_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa48eb54",
   "metadata": {},
   "source": [
    "## 读一下数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4678b144",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_path = f\"{DataConfig.coords_data_path}/1A9N_1_Q.npy\"\n",
    "data_path = f\"{DataConfig.coords_data_path}/3JBU_1_v.npy\"\n",
    "\n",
    "coords = np.load(data_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9760eda1",
   "metadata": {},
   "source": [
    "## 可视化\n",
    "\n",
    "+ 缺失值最好用相同碱基的均值填充\n",
    "+ 临近碱基通过均值计算邻域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "b2036844",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(140, 3) (140,)\n",
      "<matplotlib.colors.ListedColormap object at 0x7f2219fa14e0>\n"
     ]
    },
    {
     "data": {
      "image/png": "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PS/nvPZS90t8/Lcf55tv+qbp85jrdTI6Ospf/uVf8s///M9G1fWLDVvs2Mya7No5mqYZi5SZNx4rx+yoqkpHRweZTIbLL7+c6urqeY9pdrbY+HEXG0mSKCsrw+l0sn79evx+v+Hyam1tJZFIUFxcbAifkpISU9yNM2GFc5ONVS07F4sbK18EQaAj0sGB7gMTXlM0hRe7XuTM0BnqS+pNjctbu3YtgiDMGIQ8ntbWVtrb27n55puNbfp91uFw0NLSwurVqyfsV11dTW9vb8623t5eAoHAkrLqgC12bGaJqqrIspzT8kFflKxc8Tg7AHE+xONxDh06hCzLOJ1OU4SOPj+rLbyFxOl0UllZaVSTTiaTOZlemUzGyPQqLS1dkplec8GqYseqlh0r1P85O3p22tc7I52sKF5h/K3fi+YjfkKhELt372bPnj3cddddE+J2hoeHJ43bWb9+PUeOHMnZ9g//8A+Mjo7yjW98g7q6ukmP19jYyC9/+cucbXv37qWxsTHvuS82ttixmRa9MmkmkzFufPqPNDv41yzMtuzA/Kso9/b2cuTIEZYtW8ayZcv4wx/+YOrclnLMznzxeDzU1NRQU1NjxELp4qezsxNN03JcXmZlell1EbfanKx6nhbbsgNQVzy5QNBZEViRY1meKuA5X/GzZ88errnmGrZv387nPvc5Lr30UmRZZu/evTz66KM0NzdP2Mfj8bB58+acbbooyt7+yU9+kvPnz/P9738fgNtvv52HH36Yj3/849x66638+te/5ic/+QlPPfXUrOZqJWyxYzMl41s+jM9AMDseBgojduZaRVlVVU6ePMm5c+fYtGkTNTU1jI6Omi4iloIoWQgEQaCoqIiioiKWL19uZHqFw2EGBwdpbW3F4XBMmum11LGqZccKomIyrDCvlYGV7KzZye96foeivV5oUxREdlTvyMnKyifbaybx09DQwKuvvsoXv/hFPvrRj9Ld3U1FRQXbtm3j0Ucfnddn6u7uprOz0/h71apVPPXUU9x999184xvfYPny5Tz++ONLLu0cbLFjMwXZtXOy61Jko2+3cnsHmJtlJ5FI0NTUhKqqNDY2GubiQmWLmc1SsexMR3am18qVK1FV1Whr0d3dTUtLC26322hmWlpaisvlymt8q2BVsWNly44V5vWla780lo3V/Xo21lUVV/Gla7807X7zFT81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",
      "text/plain": [
       "<Figure size 700x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "\n",
    "\n",
    "points = np.nan_to_num(coords, nan=0.0)\n",
    "points = points[:20, :, :]\n",
    "cls_id = np.array(range(points.shape[0])).reshape(-1, 1)  # 根据基团上色\n",
    "# np.random.shuffle(cls_id)\n",
    "\n",
    "categories = np.zeros((points.shape[0], points.shape[1])) + cls_id\n",
    "categories = categories.reshape(-1)\n",
    "points = points.reshape(-1, 3)\n",
    "print(points.shape, categories.shape)\n",
    "\n",
    "\n",
    "# 创建一个新的图形\n",
    "fig = plt.figure(figsize=(7, 7))\n",
    "ax = fig.add_subplot(111, projection='3d')\n",
    "\n",
    "# 获取所有不同的类别\n",
    "unique_categories = np.unique(categories)\n",
    "\n",
    "# 为每个类别分配一种颜色\n",
    "colors = plt.colormaps.get_cmap('tab20').resampled(len(unique_categories))  # tab10', tab20', 'gist_rainbow'\n",
    "# colors = plt.colormaps['tab20c']\n",
    "print(colors)\n",
    "\n",
    "\n",
    "# 绘制点云\n",
    "for i, category in enumerate(unique_categories):\n",
    "    # 找到属于当前类别的点\n",
    "    points_in_category = points[categories == category]\n",
    "    ax.scatter(points_in_category[:, 0], points_in_category[:, 1], points_in_category[:, 2],\n",
    "               c=np.array([colors(i)]), label=f'C {category}')\n",
    "\n",
    "# 添加图例\n",
    "plt.legend()\n",
    "\n",
    "# 设置轴标签\n",
    "ax.set_xlabel('X Label')\n",
    "ax.set_ylabel('Y Label')\n",
    "ax.set_zlabel('Z Label')\n",
    "\n",
    "# 显示图形\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "0a38d3a4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': '7Y7R_1_F', 'coords': {'P': array([[-69.91799927,   1.93599999, -48.22100067],\n",
      "       [-66.27200317,  -1.19500005, -49.98099899],\n",
      "       [-63.77299881,  -5.46999979, -52.2120018 ],\n",
      "       [-62.18999863, -11.99199963, -52.14400101],\n",
      "       [-62.84999847, -17.57600021, -49.36600113]]), \"O5'\": array([[-68.59600067,   1.08399999, -47.99100113],\n",
      "       [-64.91200256,  -2.01900005, -50.04999924],\n",
      "       [-62.77000046,  -6.65700006, -52.55899811],\n",
      "       [-62.17200089, -12.90200043, -50.83399963],\n",
      "       [-63.23500061, -17.98800087, -47.87099838]]), \"C5'\": array([[-67.82099915,   1.26199996, -46.81800079],\n",
      "       [-63.72200012,  -1.421     , -50.53900146],\n",
      "       [-62.90000153,  -7.93100023, -51.9469986 ],\n",
      "       [-61.01300049, -13.64799976, -50.50699997],\n",
      "       [-62.36600113, -18.75799942, -47.04299927]]), \"C4'\": array([[-66.35099792,   1.37800002, -47.13299942],\n",
      "       [-62.52600098,  -2.31100011, -50.31200027],\n",
      "       [-61.61500168,  -8.3739996 , -51.2820015 ],\n",
      "       [-61.00299835, -14.13000011, -49.07799911],\n",
      "       [-63.07400131, -19.18000031, -45.78300095]]), \"C3'\": array([[-65.71099854,   0.154     , -47.77999878],\n",
      "       [-62.76800156,  -3.80599999, -50.4469986 ],\n",
      "       [-61.61000061,  -9.81499958, -50.77999878],\n",
      "       [-62.01499939, -15.19099998, -48.68299866],\n",
      "       [-64.42099762, -19.875     , -45.97600174]]), \"O3'\": array([[-65.86499786,   0.15000001, -49.19400024],\n",
      "       [-62.80099869,  -4.2579999 , -51.79100037],\n",
      "       [-61.23699951, -10.74400043, -51.78499985],\n",
      "       [-61.69300079, -16.48200035, -49.16500092],\n",
      "       [         nan,          nan,          nan]])}, 'seq': 'CGACG'}\n"
     ]
    }
   ],
   "source": [
    "# Define RNADataset Class and Seeding Function\n",
    "class RNADatasetV2(Dataset):\n",
    "    def __init__(self, data_path, is_train=True):\n",
    "        super(RNADatasetV2, self).__init__()\n",
    "        self.npy_dir = data_path + \"/coords\"\n",
    "        self.name_list = [i[:-4] for i in os.listdir(data_path + \"/coords\")]\n",
    "        self.seq_dir =  data_path + \"/seqs/\"\n",
    "        self.cache = {}\n",
    "        self.is_train = is_train\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.name_list)\n",
    "\n",
    "    def get_pdb_id(self, idx):\n",
    "        return self.name_list[idx]\n",
    "\n",
    "    def merge_coords_file_path(self, pdb_id):\n",
    "        return os.path.join(self.npy_dir, pdb_id + '.npy')\n",
    "\n",
    "    def load_feature(self, pdb_id):\n",
    "        coords = np.load(self.merge_coords_file_path(pdb_id))\n",
    "        feature = {\n",
    "            \"name\": pdb_id,\n",
    "            \"coords\": {\n",
    "                \"P\": coords[:, 0, :],\n",
    "                \"O5'\": coords[:, 1, :],\n",
    "                \"C5'\": coords[:, 2, :],\n",
    "                \"C4'\": coords[:, 3, :],\n",
    "                \"C3'\": coords[:, 4, :],\n",
    "                \"O3'\": coords[:, 5, :],\n",
    "            }\n",
    "        }\n",
    "\n",
    "        return feature\n",
    "    \n",
    "    def load_seq(self, pdb_id):\n",
    "        return list(read_fasta_biopython(self.seq_dir + pdb_id + \".fasta\").values())[0]\n",
    "    \n",
    "    def first_load(self, idx):\n",
    "        pdb_id = self.get_pdb_id(idx)\n",
    "        feature = self.load_feature(pdb_id)\n",
    "        if self.is_train:\n",
    "            feature[\"seq\"] = self.load_seq(pdb_id)\n",
    "        else:\n",
    "            feature[\"seq\"] = None\n",
    "        return feature\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        if idx in self.cache:\n",
    "            return self.cache[idx]\n",
    "        else:\n",
    "            data = self.first_load(idx)\n",
    "            self.cache[idx] = data\n",
    "            return data\n",
    "    \n",
    "    def __iter__(self):\n",
    "        for idx in range(len(self)):\n",
    "            yield self.__getitem__(idx)\n",
    "\n",
    "    def get_lengths_by_indices(self, indices):\n",
    "        lengths = []\n",
    "        for idx in indices:\n",
    "            pdb_id = self.get_pdb_id(idx)\n",
    "            file_path = self.merge_coords_file_path(pdb_id)\n",
    "            with open(file_path, 'rb') as f:\n",
    "                # 读取文件头的前8字节（魔数和版本号）\n",
    "                version = np.lib.format.read_magic(f)\n",
    "                # 读取文件头信息（包含shape/dtype等）\n",
    "                shape, _, _ = np.lib.format._read_array_header(f, version)\n",
    "            lengths.append(shape[0])\n",
    "        return lengths\n",
    "    \n",
    "dataset = RNADatasetV2(\n",
    "    data_path=DataConfig.datapath,\n",
    "    is_train=True\n",
    ")\n",
    "print(dataset[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "bffd6013-4f5b-42bf-9b05-42bd6041daa9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "seeding done!!!\n"
     ]
    }
   ],
   "source": [
    "def seeding(seed):\n",
    "    np.random.seed(seed)\n",
    "    random.seed(seed)\n",
    "    os.environ['PYTHONHASHSEED'] = str(seed)\n",
    "    torch.manual_seed(seed)\n",
    "    torch.cuda.manual_seed(seed)\n",
    "    torch.cuda.manual_seed_all(seed)\n",
    "    torch.backends.cudnn.deterministic = True\n",
    "    torch.backends.cudnn.benchmark = False\n",
    "    print('seeding done!!!')\n",
    "config = Config()\n",
    "data_config = config.data_config\n",
    "train_config = config.train_config\n",
    "seeding(config.seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "85a61f93-e518-4d50-aa87-9e4bc1f74516",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.utils.data import DataLoader, random_split\n",
    "\n",
    "train_dataset, valid_dataset = random_split(dataset, lengths=[int(0.9 * len(dataset)), len(dataset) -  int(0.9 * len(dataset))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "44892589",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'5MSG_1_M'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_dataset[0]['name']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5dbc500a",
   "metadata": {},
   "source": [
    "### RNA Inverse Folding Framework\n",
    "\n",
    "This framework integrates geometric featurization with GNNs to predict RNA sequences compatible with input 3D conformations.\n",
    "该框架将几何特征化与图神经网络（GNNs）相结合，用于预测与输入三维构象兼容的RNA序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e049e40a",
   "metadata": {},
   "outputs": [],
   "source": [
    "def prepare_rna_batch(rna_samples):\n",
    "    \"\"\"将RNA样本批次转换为神经网络可用的张量格式\n",
    "    \n",
    "    参数:\n",
    "        rna_samples: 包含多个RNA样本的列表，每个样本应包含:\n",
    "            - 'seq': 碱基序列字符串(如\"AUCG\")\n",
    "            - 'coords': 原子坐标字典\n",
    "            - 'name': 样本标识名\n",
    "    \n",
    "    返回:\n",
    "        features: 形状[B, L_max, 6, 3]的原子坐标张量\n",
    "        labels: 形状[B, L_max]的碱基类别张量  \n",
    "        valid_mask: 有效位置掩码\n",
    "        seq_lengths: 各样本实际长度\n",
    "        sample_names: 样本名称列表\n",
    "    \"\"\"\n",
    "    tag_list = list(\"AUCG\")\n",
    "    idx2tag = {i: tag for i, tag in enumerate(tag_list)}\n",
    "    tag2idx = {tag: i for i, tag in enumerate(tag_list)}\n",
    "    # KEY_ATOMS = [\"P\", \"O5'\", \"C5'\", \"C4'\", \"C3'\", \"O3'\", \"N\"]\n",
    "    KEY_ATOMS = [\"P\", \"O5'\", \"C5'\", \"C4'\", \"C3'\", \"O3'\"]\n",
    "    \n",
    "    # 初始化维度\n",
    "    batch_size = len(rna_samples)\n",
    "    seq_lengths = [b[\"coords\"][\"P\"].shape[0] for b in rna_samples]  # 获取RNA序列长度\n",
    "    max_len = max(seq_lengths)  # 当前batch最大长度\n",
    "    \n",
    "    # 预分配张量（直接初始化为最终类型）\n",
    "    coords = np.zeros((batch_size, max_len, 6, 3), dtype=np.float32)  # batch, 序列长度，6个原子位置，每个原子坐标\n",
    "    labels = np.full((batch_size, max_len), -1, dtype=np.int64)\n",
    "    mask = np.zeros((batch_size, max_len), dtype=np.float32)\n",
    "    \n",
    "    for i, sample in enumerate(rna_samples):\n",
    "        curr_len = seq_lengths[i]\n",
    "        # 向量化处理原子坐标\n",
    "        atom_stack = np.stack([np.nan_to_num(sample['coords'][atom], nan=0.0) for atom in KEY_ATOMS],\n",
    "                              axis=1)  # N 6 3\n",
    "        # 有效位置标记\n",
    "        valid_pos = np.isfinite(atom_stack.sum((1,2)))\n",
    "        actual_len = min(curr_len, sum(valid_pos))\n",
    "        # 单样本赋值\n",
    "        coords[i,:actual_len] = atom_stack[valid_pos][:actual_len]\n",
    "        mask[i,:actual_len] = 1.0\n",
    "        \n",
    "        # 有标签的话读取标签\n",
    "        seq = np.array([c for c in sample['seq']], dtype=np.str_)  # 字符串转列表再转numpy\n",
    "        labels[i,:actual_len] = [tag2idx[b] for b in seq[valid_pos][:actual_len]]\n",
    "    \n",
    "    features, labels, valid_mask, seq_lengths, sample_names = (torch.from_numpy(coords),\n",
    "        torch.from_numpy(labels),\n",
    "        torch.from_numpy(mask),\n",
    "        np.array(seq_lengths),\n",
    "        [s['name'] for s in rna_samples])\n",
    "    \n",
    "    return features, labels, valid_mask, seq_lengths, sample_names\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "318463dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# prepare_rna_batch([train_dataset[0]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "0d8d9a12-eb92-404f-8cd4-0998d310c1f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_loader = DataLoader(train_dataset,\n",
    "        batch_size=train_config.batch_size,\n",
    "        shuffle=True,\n",
    "        num_workers=0,\n",
    "        collate_fn=prepare_rna_batch)\n",
    "\n",
    "valid_loader = DataLoader(valid_dataset,\n",
    "        batch_size=train_config.batch_size,\n",
    "        shuffle=False,\n",
    "        num_workers=0,\n",
    "        collate_fn=prepare_rna_batch)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "1ed12564-029e-496c-8826-29f98c6b580c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def gather_edges(edges, neighbor_idx):\n",
    "    neighbors = neighbor_idx.unsqueeze(-1).expand(-1, -1, -1, edges.size(-1))\n",
    "    return torch.gather(edges, 2, neighbors)\n",
    "\n",
    "def gather_nodes(nodes, neighbor_idx):\n",
    "    neighbors_flat = neighbor_idx.view((neighbor_idx.shape[0], -1))\n",
    "    neighbors_flat = neighbors_flat.unsqueeze(-1).expand(-1, -1, nodes.size(2))\n",
    "    neighbor_features = torch.gather(nodes, 1, neighbors_flat)\n",
    "    neighbor_features = neighbor_features.view(list(neighbor_idx.shape)[:3] + [-1])\n",
    "    return neighbor_features\n",
    "\n",
    "def gather_nodes_t(nodes, neighbor_idx):\n",
    "    idx_flat = neighbor_idx.unsqueeze(-1).expand(-1, -1, nodes.size(2))\n",
    "    return torch.gather(nodes, 1, idx_flat)\n",
    "\n",
    "def cat_neighbors_nodes(h_nodes, h_neighbors, E_idx):\n",
    "    h_nodes = gather_nodes(h_nodes, E_idx)\n",
    "    return torch.cat([h_neighbors, h_nodes], -1)\n",
    "\n",
    "\n",
    "class MPNNLayer(nn.Module):\n",
    "    # 简单的聚合边特征到节点特征\n",
    "    def __init__(self, num_hidden, num_in, dropout=0.1, num_heads=None, scale=30):\n",
    "        super(MPNNLayer, self).__init__()\n",
    "        self.num_hidden = num_hidden\n",
    "        self.num_in = num_in\n",
    "        self.scale = scale\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        self.norm1 = nn.LayerNorm(num_hidden)\n",
    "        self.norm2 = nn.LayerNorm(num_hidden)\n",
    "\n",
    "        self.W1 = nn.Linear(num_hidden + num_in, num_hidden, bias=True)\n",
    "        self.W2 = nn.Linear(num_hidden, num_hidden, bias=True)\n",
    "        self.W3 = nn.Linear(num_hidden, num_hidden, bias=True)\n",
    "        self.act = nn.ReLU()\n",
    "\n",
    "        self.dense = nn.Sequential(\n",
    "            nn.Linear(num_hidden, num_hidden*4),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(num_hidden*4, num_hidden)\n",
    "        )\n",
    "\n",
    "    def forward(self, h_V, h_E, edge_idx, batch_id=None):\n",
    "        src_idx, dst_idx = edge_idx[0], edge_idx[1]\n",
    "        h_message = self.W3(self.act(self.W2(self.act(self.W1(h_E)))))\n",
    "        # 特征聚合, 按源节点聚合，即分组相加\n",
    "        dh = scatter_sum(h_message, src_idx, dim=0) / self.scale\n",
    "        # 随机丢一些边的特征\n",
    "        h_V = self.norm1(h_V + self.dropout(dh))\n",
    "        # skip-connection\n",
    "        dh = self.dense(h_V)\n",
    "        h_V = self.norm2(h_V + self.dropout(dh))\n",
    "        return h_V\n",
    "\n",
    "\n",
    "class Normalize(nn.Module):\n",
    "    def __init__(self, size, epsilon=1e-6):\n",
    "        super(Normalize, self).__init__()\n",
    "        self.gain = nn.Parameter(torch.ones(size))  # 注册为模型参数，自动启用梯度，自动进行优化器更新\n",
    "        self.bias = nn.Parameter(torch.zeros(size))\n",
    "        self.epsilon = epsilon\n",
    "\n",
    "    def forward(self, x, dim=-1):\n",
    "        mu = x.mean(dim, keepdim=True)\n",
    "        sigma = torch.sqrt(x.var(dim, keepdim=True) + self.epsilon)\n",
    "        gain = self.gain\n",
    "        bias = self.bias\n",
    "        if dim != -1:\n",
    "            shape = [1] * len(mu.size())\n",
    "            shape[dim] = self.gain.size()[0]\n",
    "            gain = gain.view(shape)\n",
    "            bias = bias.view(shape)\n",
    "        return gain * (x - mu) / (sigma + self.epsilon) + bias\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "102ead4b-e635-464b-a3c2-68bda9f2e9fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "feat_dims = {\n",
    "    'node': {\n",
    "        'angle': 12,\n",
    "        'distance': 80,\n",
    "        'direction': 9,\n",
    "    },\n",
    "    'edge': {\n",
    "        'orientation': 4,\n",
    "        'distance': 96,\n",
    "        'direction': 15,\n",
    "    }\n",
    "}\n",
    "\n",
    "def nan_to_num(tensor, nan=0.0):\n",
    "    idx = torch.isnan(tensor)\n",
    "    tensor[idx] = nan\n",
    "    return tensor\n",
    "\n",
    "def _normalize(tensor, dim=-1):\n",
    "    return nan_to_num(\n",
    "        torch.div(tensor, torch.norm(tensor, dim=dim, keepdim=True)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "394e9ca4",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2822485/775164200.py:106: UserWarning: Using torch.cross without specifying the dim arg is deprecated.\n",
      "Please either pass the dim explicitly or simply use torch.linalg.cross.\n",
      "The default value of dim will change to agree with that of linalg.cross in a future release. (Triggered internally at ../aten/src/ATen/native/Cross.cpp:62.)\n",
      "  n_0 = _normalize(torch.cross(u_0, u_1), dim=-1)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(tensor([[ 0.6665, -0.5076,  0.8455,  ...,  1.6935,  0.7038,  0.5538],\n",
       "         [-0.5101,  0.9970,  0.3257,  ...,  0.9437,  1.5440, -0.4673],\n",
       "         [-1.4782,  0.2026,  0.2188,  ...,  0.8391,  1.6782, -0.0041],\n",
       "         ...,\n",
       "         [ 0.4365, -1.4673, -0.0448,  ..., -0.7373,  1.6570, -0.6621],\n",
       "         [ 0.5971, -0.3675,  0.2021,  ...,  0.7507,  0.6637, -0.6297],\n",
       "         [-2.0501,  0.4453, -0.4989,  ...,  1.3144,  1.9879,  0.5882]],\n",
       "        grad_fn=<AddBackward0>),\n",
       " tensor([[ 0.0353, -0.3392,  0.2620,  ...,  0.0826, -1.3114,  0.4961],\n",
       "         [-1.0941, -0.7947,  1.3619,  ...,  0.5078, -1.1088,  0.6581],\n",
       "         [-0.8143, -0.7444,  0.8037,  ...,  0.6425, -0.7995,  0.8912],\n",
       "         ...,\n",
       "         [-0.4603, -0.3871,  0.9783,  ...,  0.5033,  0.2598, -0.6265],\n",
       "         [-0.4554, -0.1143,  1.4058,  ...,  0.5450, -0.1879, -0.5257],\n",
       "         [-0.4055,  0.1478,  0.7166,  ...,  0.2878,  0.4015, -1.4946]],\n",
       "        grad_fn=<AddBackward0>),\n",
       " tensor([[  0,   0,   0,  ..., 127, 127, 127],\n",
       "         [  0,  85,  22,  ...,  55,   6, 101]]),\n",
       " tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0]))"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from torch_geometric.data import Data, Batch\n",
    "\n",
    "\n",
    "# 图结构数据生成器\n",
    "class RNAGraphBuilder(nn.Module):\n",
    "    # 边特征维度，结点特征维度，结点特征类型，边特征类型，RBF核数，K近邻数，数据增强，dropout\n",
    "    # 结点特征：['angle', 'distance', 'direction'], 边特征：['orientation', 'distance', 'direction']\n",
    "\n",
    "    def __init__(self, edge_features, node_features, num_rbf=16, top_k=30, augment_eps=0.):\n",
    "        super(RNAGraphBuilder, self).__init__()\n",
    "        self.num_rbf = num_rbf\n",
    "        self.top_k = top_k\n",
    "        # 随机增强系数\n",
    "        self.augment_eps = augment_eps\n",
    "        \n",
    "        self.node_feat_types = ['angle', 'distance', 'direction']\n",
    "        self.edge_feat_types = ['orientation', 'distance', 'direction']\n",
    "        node_in = sum([feat_dims['node'][feat] for feat in self.node_feat_types])\n",
    "        edge_in = sum([feat_dims['edge'][feat] for feat in self.edge_feat_types])\n",
    "        self.node_embedding = nn.Linear(node_in,  node_features, bias=True)\n",
    "        self.edge_embedding = nn.Linear(edge_in, edge_features, bias=True)\n",
    "        self.norm_nodes = Normalize(node_features)\n",
    "        self.norm_edges = Normalize(edge_features)\n",
    "\n",
    "\n",
    "    @staticmethod\n",
    "    def build_graph(coord, seq, k_neighbors):\n",
    "        \"\"\"将坐标和序列转换为图结构\"\"\"\n",
    "        num_nodes = coord.shape[0]\n",
    "        # 节点特征：展平每个节点的7个骨架点坐标\n",
    "        x = torch.tensor(coord.reshape(num_nodes, -1), dtype=torch.float32)  # [N, 7*3]\n",
    "        \n",
    "        # 边构建：基于序列顺序的k近邻连接\n",
    "        edge_index = []\n",
    "        for i in range(num_nodes):\n",
    "            # 连接前k和后k个节点\n",
    "            neighbors = list(range(max(0, i-k_neighbors), i)) + \\\n",
    "                       list(range(i+1, min(num_nodes, i+1+k_neighbors)))\n",
    "            for j in neighbors:\n",
    "                edge_index.append([i, j])\n",
    "                edge_index.append([j, i])  # 双向连接\n",
    "        \n",
    "        edge_index = torch.tensor(edge_index, dtype=torch.long).t().contiguous()\n",
    "        # 节点标签\n",
    "        y = torch.tensor([Config.seq_vocab.index(c) for c in seq], dtype=torch.long)\n",
    "        return Data(x=x, edge_index=edge_index, y=y, num_nodes=num_nodes)\n",
    "\n",
    "\n",
    "    def _dist(self, X, mask, top_k, eps=1E-6):\n",
    "        mask_2D = torch.unsqueeze(mask,1) * torch.unsqueeze(mask,2)  # 两两之间求掩码 B, N -> B, N, N\n",
    "        dX = torch.unsqueeze(X, 1) - torch.unsqueeze(X, 2)  # 两两之间求距离 B, N, 3 -> B, N, N, 3\n",
    "        D = (1. - mask_2D)*10000 + mask_2D* torch.sqrt(torch.sum(dX**2, 3) + eps)  #  B, N, N 求欧式距离, 无效值距离设置10000的很大值\n",
    "        D_max, _ = torch.max(D, -1, keepdim=True)  # 获取每行的最大值\n",
    "        D_adjust = D + (1. - mask_2D) * (D_max+1)  # 无效值设置为最大值+1, 不会被选中\n",
    "        D_neighbors, E_idx = torch.topk(D_adjust, min(top_k, D_adjust.shape[-1]), dim=-1, largest=False) # 选择topk近邻\n",
    "        return D_neighbors, E_idx  # 返回每个节点的邻居特征和邻居索引\n",
    "\n",
    "\n",
    "    def _rbf(self, D, num_rbf):\n",
    "        D_min, D_max, D_count = 0., 20., num_rbf\n",
    "        D_mu = torch.linspace(D_min, D_max, D_count, device=D.device)\n",
    "        D_mu = D_mu.view([1,1,1,-1])\n",
    "        D_sigma = (D_max - D_min) / D_count\n",
    "        D_expand = torch.unsqueeze(D, -1)\n",
    "        return torch.exp(-((D_expand - D_mu) / D_sigma)**2)\n",
    "\n",
    "\n",
    "    def _get_rbf(self, A, B, E_idx=None, num_rbf=16):\n",
    "        if E_idx is not None:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,None,:,:])**2,-1) + 1e-6)\n",
    "            D_A_B_neighbors = gather_edges(D_A_B[:,:,:,None], E_idx)[:,:,:,0]\n",
    "            RBF_A_B = self._rbf(D_A_B_neighbors, num_rbf)\n",
    "        else:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,:,None,:])**2, -1) + 1e-6)\n",
    "            RBF_A_B = self._rbf(D_A_B, num_rbf)\n",
    "        return RBF_A_B\n",
    "\n",
    "\n",
    "    def _quaternions(self, R):\n",
    "        diag = torch.diagonal(R, dim1=-2, dim2=-1)\n",
    "        Rxx, Ryy, Rzz = diag.unbind(-1)\n",
    "        magnitudes = 0.5 * torch.sqrt(torch.abs(1 + torch.stack([\n",
    "              Rxx - Ryy - Rzz, \n",
    "            - Rxx + Ryy - Rzz, \n",
    "            - Rxx - Ryy + Rzz\n",
    "        ], -1)))\n",
    "        _R = lambda i,j: R[:,:,:,i,j]\n",
    "        signs = torch.sign(torch.stack([\n",
    "            _R(2,1) - _R(1,2),\n",
    "            _R(0,2) - _R(2,0),\n",
    "            _R(1,0) - _R(0,1)\n",
    "        ], -1))\n",
    "        xyz = signs * magnitudes\n",
    "        w = torch.sqrt(F.relu(1 + diag.sum(-1, keepdim=True))) / 2.\n",
    "        Q = torch.cat((xyz, w), -1)\n",
    "        Q = F.normalize(Q, dim=-1)\n",
    "        return Q\n",
    "\n",
    "\n",
    "    def _orientations_coarse(self, X, E_idx, eps=1e-6):\n",
    "        V = X.clone()\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3) \n",
    "        dX = X[:,1:,:] - X[:,:-1,:]\n",
    "        U = _normalize(dX, dim=-1)\n",
    "        u_0, u_1 = U[:,:-2,:], U[:,1:-1,:]\n",
    "        n_0 = _normalize(torch.cross(u_0, u_1), dim=-1)\n",
    "        b_1 = _normalize(u_0 - u_1, dim=-1)\n",
    "        \n",
    "        # select C3'\n",
    "        n_0 = n_0[:,4::6,:] \n",
    "        b_1 = b_1[:,4::6,:]\n",
    "        X = X[:,4::6,:]\n",
    "\n",
    "        Q = torch.stack((b_1, n_0, torch.cross(b_1, n_0)), 2)\n",
    "        Q = Q.view(list(Q.shape[:2]) + [9])\n",
    "        Q = F.pad(Q, (0,0,0,1), 'constant', 0) # [16, 464, 9]\n",
    "\n",
    "        Q_neighbors = gather_nodes(Q, E_idx) # [16, 464, 30, 9]\n",
    "        P_neighbors = gather_nodes(V[:,:,0,:], E_idx) # [16, 464, 30, 3]\n",
    "        O5_neighbors = gather_nodes(V[:,:,1,:], E_idx)\n",
    "        C5_neighbors = gather_nodes(V[:,:,2,:], E_idx)\n",
    "        C4_neighbors = gather_nodes(V[:,:,3,:], E_idx)\n",
    "        O3_neighbors = gather_nodes(V[:,:,5,:], E_idx)\n",
    "        \n",
    "        Q = Q.view(list(Q.shape[:2]) + [3,3]).unsqueeze(2) # [16, 464, 1, 3, 3]\n",
    "        Q_neighbors = Q_neighbors.view(list(Q_neighbors.shape[:3]) + [3,3]) # [16, 464, 30, 3, 3]\n",
    "\n",
    "        dX = torch.stack([P_neighbors,O5_neighbors,C5_neighbors,C4_neighbors,O3_neighbors], dim=3) - X[:,:,None,None,:] # [16, 464, 30, 3]\n",
    "        dU = torch.matmul(Q[:,:,:,None,:,:], dX[...,None]).squeeze(-1) # [16, 464, 30, 3] 邻居的相对坐标\n",
    "        B, N, K = dU.shape[:3]\n",
    "        E_direct = _normalize(dU, dim=-1)\n",
    "        E_direct = E_direct.reshape(B, N, K,-1)\n",
    "        R = torch.matmul(Q.transpose(-1,-2), Q_neighbors)\n",
    "        E_orient = self._quaternions(R)\n",
    "        \n",
    "        dX_inner = V[:,:,[0,2,3],:] - X.unsqueeze(-2)\n",
    "        dU_inner = torch.matmul(Q, dX_inner.unsqueeze(-1)).squeeze(-1)\n",
    "        dU_inner = _normalize(dU_inner, dim=-1)\n",
    "        V_direct = dU_inner.reshape(B,N,-1)\n",
    "        return V_direct, E_direct, E_orient\n",
    "\n",
    "\n",
    "    def _dihedrals(self, X, eps=1e-7):\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3)\n",
    "\n",
    "        # Shifted slices of unit vectors\n",
    "        # https://iupac.qmul.ac.uk/misc/pnuc2.html#220\n",
    "        # https://x3dna.org/highlights/torsion-angles-of-nucleic-acid-structures\n",
    "        # alpha:   O3'_{i-1} P_i O5'_i C5'_i\n",
    "        # beta:    P_i O5'_i C5'_i C4'_i\n",
    "        # gamma:   O5'_i C5'_i C4'_i C3'_i\n",
    "        # delta:   C5'_i C4'_i C3'_i O3'_i\n",
    "        # epsilon: C4'_i C3'_i O3'_i P_{i+1}\n",
    "        # zeta:    C3'_i O3'_i P_{i+1} O5'_{i+1} \n",
    "        # What's more:\n",
    "        #   chi: C1' - N9 \n",
    "        #   chi is different for (C, T, U) and (A, G) https://x3dna.org/highlights/the-chi-x-torsion-angle-characterizes-base-sugar-relative-orientation\n",
    "\n",
    "        dX = X[:, 5:, :] - X[:, :-5, :] # O3'-P, P-O5', O5'-C5', C5'-C4', ...\n",
    "        U = F.normalize(dX, dim=-1)\n",
    "        u_2 = U[:,:-2,:]  # O3'-P, P-O5', ...\n",
    "        u_1 = U[:,1:-1,:] # P-O5', O5'-C5', ...\n",
    "        u_0 = U[:,2:,:]   # O5'-C5', C5'-C4', ...\n",
    "        # Backbone normals\n",
    "        n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)\n",
    "        n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)\n",
    "\n",
    "        # Angle between normals\n",
    "        cosD = (n_2 * n_1).sum(-1)\n",
    "        cosD = torch.clamp(cosD, -1+eps, 1-eps)\n",
    "        D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)\n",
    "        \n",
    "        D = F.pad(D, (3,4), 'constant', 0)\n",
    "        D = D.view((D.size(0), D.size(1) //6, 6))\n",
    "        return torch.cat((torch.cos(D), torch.sin(D)), 2) # return D_features\n",
    "\n",
    "\n",
    "    def encode_node_features(self, X, mask_bool, E_idx):\n",
    "        # node features\n",
    "        h_V = []\n",
    "        node_mask_select = lambda x: torch.masked_select(x, mask_bool.unsqueeze(-1)).reshape(-1, x.shape[-1])\n",
    "        node_feat_types = self.node_feat_types\n",
    "        # angle\n",
    "        V_angle = node_mask_select(self._dihedrals(X))\n",
    "        # distance\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        node_list = ['O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        V_dist = []\n",
    "        for pair in node_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            V_dist.append(node_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], None, self.num_rbf).squeeze()))\n",
    "        V_dist = torch.cat(tuple(V_dist), dim=-1).squeeze()\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        V_direct = node_mask_select(V_direct)\n",
    "        if 'angle' in node_feat_types:\n",
    "            h_V.append(V_angle)\n",
    "        if 'distance' in node_feat_types:\n",
    "            h_V.append(V_dist)\n",
    "        if 'direction' in node_feat_types:\n",
    "            h_V.append(V_direct)\n",
    "        \n",
    "        return self.node_embedding(torch.cat(h_V, dim=-1))\n",
    "\n",
    "    def encode_edge_features(self, X, mask_attend, E_idx):\n",
    "        # edge features\n",
    "        h_E = []\n",
    "        edge_mask_select = lambda x: torch.masked_select(x, mask_attend.unsqueeze(-1)).reshape(-1,x.shape[-1])\n",
    "        edge_feat_types = self.edge_feat_types\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        E_direct, E_orient = list(map(lambda x: edge_mask_select(x), [E_direct, E_orient]))\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        edge_list = ['P-P', 'O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        E_dist = [] \n",
    "        for pair in edge_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            E_dist.append(edge_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], E_idx, self.num_rbf)))\n",
    "        E_dist = torch.cat(tuple(E_dist), dim=-1)\n",
    "        \n",
    "        if 'orientation' in edge_feat_types:\n",
    "            h_E.append(E_orient)\n",
    "        if 'distance' in edge_feat_types:\n",
    "            h_E.append(E_dist)\n",
    "        if 'direction' in edge_feat_types:\n",
    "            h_E.append(E_direct)\n",
    "        return self.edge_embedding(torch.cat(h_E, dim=-1))\n",
    "\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        \"\"\"\n",
    "        X: [B, N, 6, 3], batch,  N最大序列长度，6个原子位置，每个原子坐标\n",
    "        mask: [B, N]  # 标识每个样本序列的有效长度1有效，0无效\n",
    "        \"\"\"\n",
    "        if self.training and self.augment_eps > 0:\n",
    "            X = X + self.augment_eps * torch.randn_like(X)\n",
    "\n",
    "        # Build k-Nearest Neighbors graph\n",
    "        B, N, _,_ = X.shape\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        # atom_N19_ = X[:, :, 6, :]\n",
    "\n",
    "        X_backbone = atom_P  # 以P基团为中心判断邻域\n",
    "        D_neighbors, E_idx = self._dist(X_backbone, mask, self.top_k) # 获取topk近邻  返回每个节点的邻居和邻居id\n",
    "\n",
    "        mask_bool = (mask==1)\n",
    "        mask_attend = gather_nodes(mask.unsqueeze(-1), E_idx).squeeze(-1)\n",
    "        mask_attend = (mask.unsqueeze(-1) * mask_attend) == 1\n",
    "        \n",
    "        h_V = self.encode_node_features(X, mask_bool, E_idx)\n",
    "        h_E = self.encode_edge_features(X, mask_attend, E_idx)\n",
    "        \n",
    "        # Embed the nodes\n",
    "        h_V = self.norm_nodes(h_V)\n",
    "        h_E = self.norm_edges(h_E)\n",
    "\n",
    "        # prepare the variables to return\n",
    "        shift = mask.sum(dim=1).cumsum(dim=0) - mask.sum(dim=1)  # cumsum累积求和\n",
    "        src = shift.view(B,1,1) + E_idx\n",
    "        src = torch.masked_select(src, mask_attend).view(1,-1)\n",
    "        dst = shift.view(B,1,1) + torch.arange(0, N, device=src.device).view(1,-1,1).expand_as(mask_attend)\n",
    "        dst = torch.masked_select(dst, mask_attend).view(1,-1)\n",
    "        E_idx = torch.cat((dst, src), dim=0).long()\n",
    "\n",
    "        sparse_idx = mask.nonzero()\n",
    "        X = X[sparse_idx[:,0], sparse_idx[:,1], :, :]\n",
    "        batch_id = sparse_idx[:,0]\n",
    "        return h_V, h_E, E_idx, batch_id\n",
    "    \n",
    "X = torch.randn(1, 128, 6, 3)\n",
    "mask = torch.ones(1, 128)\n",
    "rna_graph = RNAGraphBuilder(128, 128)\n",
    "rna_graph(X, mask)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "45a6f369",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.4191, 1.0000, 0.0757, 0.3712],\n",
       "        [0.4503, 0.4770, 1.0000, 0.8607],\n",
       "        [0.3274, 0.4715, 1.0000, 0.2640]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "\n",
    "# 示例：3x4张量，将最后一个维度的第2个索引统一置1\n",
    "tensor = torch.rand(3, 4)\n",
    "indices = torch.tensor([[1], [2], [2]])  # 所有行目标索引相同\n",
    "src = torch.ones_like(indices, dtype=tensor.dtype)\n",
    "tensor.scatter_(1, indices, src)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "146b368d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[0.5163, 0.5952, 1.0000, 0.5675],\n",
       "         [0.7706, 0.8248, 1.0000, 0.1118],\n",
       "         [0.0231, 0.5398, 1.0000, 0.2070]]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "\n",
    "# 示例：3x4张量，将最后一个维度的第2个索引统一置1\n",
    "tensor = torch.rand(1, 3, 4)\n",
    "indices = torch.tensor([[[2], [2], [2]]])  # 所有行目标索引相同\n",
    "src = torch.ones_like(indices, dtype=tensor.dtype)\n",
    "tensor.scatter_(-1, indices, src)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "697bd529",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 3, 1])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "indices.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "05186b76",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "class RNAFeatures(nn.Module):\n",
    "    def __init__(self, edge_features, node_features, node_feat_types=[], edge_feat_types=[], num_rbf=16, top_k=30,\n",
    "                 augment_eps=0., dropout=0.1):\n",
    "        super(RNAFeatures, self).__init__()\n",
    "        \"\"\"Extract RNA Features\"\"\"\n",
    "        self.edge_features = edge_features\n",
    "        self.node_features = node_features\n",
    "        self.top_k = top_k\n",
    "        self.augment_eps = augment_eps\n",
    "        self.num_rbf = num_rbf\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        self.node_feat_types = node_feat_types\n",
    "        self.edge_feat_types = edge_feat_types\n",
    "\n",
    "        node_in = sum([feat_dims['node'][feat] for feat in node_feat_types])\n",
    "        edge_in = sum([feat_dims['edge'][feat] for feat in edge_feat_types])\n",
    "        self.node_embedding = nn.Linear(node_in, node_features, bias=True)\n",
    "        self.edge_embedding = nn.Linear(edge_in, edge_features, bias=True)\n",
    "        self.norm_nodes = Normalize(node_features)\n",
    "        self.norm_edges = Normalize(edge_features)\n",
    "\n",
    "    def _dist(self, X, mask, eps=1E-6):\n",
    "        mask_2D = torch.unsqueeze(mask, 1) * torch.unsqueeze(mask, 2)\n",
    "        dX = torch.unsqueeze(X, 1) - torch.unsqueeze(X, 2)\n",
    "        D = (1. - mask_2D) * 10000 + mask_2D * torch.sqrt(torch.sum(dX ** 2, 3) + eps)\n",
    "\n",
    "        D_max, _ = torch.max(D, -1, keepdim=True)\n",
    "        D_adjust = D + (1. - mask_2D) * (D_max + 1)\n",
    "        D_neighbors, E_idx = torch.topk(D_adjust, min(self.top_k, D_adjust.shape[-1]), dim=-1, largest=False)\n",
    "        return D_neighbors, E_idx\n",
    "\n",
    "    def _rbf(self, D):\n",
    "        D_min, D_max, D_count = 0., 20., self.num_rbf\n",
    "        D_mu = torch.linspace(D_min, D_max, D_count, device=D.device)\n",
    "        D_mu = D_mu.view([1, 1, 1, -1])\n",
    "        D_sigma = (D_max - D_min) / D_count\n",
    "        D_expand = torch.unsqueeze(D, -1)\n",
    "        return torch.exp(-((D_expand - D_mu) / D_sigma) ** 2)\n",
    "\n",
    "    def _get_rbf__node(self, A, B):\n",
    "        D_A_B = torch.sqrt(torch.sum((A[:, :, None, :] - B[:, :, None, :]) ** 2, -1) + 1e-6)\n",
    "        return self._rbf(D_A_B)\n",
    "\n",
    "    def _get_rbf__edge(self, A, B, E_idx):\n",
    "        D_A_B = torch.sqrt(torch.sum((A[:, :, None, :] - B[:, None, :, :]) ** 2, -1) + 1e-6)\n",
    "        D_A_B_neighbors = gather_edges(D_A_B[:, :, :, None], E_idx)[:, :, :, 0]\n",
    "        return self._rbf(D_A_B_neighbors)\n",
    "\n",
    "    def _quaternions(self, R):\n",
    "        diag = torch.diagonal(R, dim1=-2, dim2=-1)\n",
    "        Rxx, Ryy, Rzz = diag.unbind(-1)\n",
    "        magnitudes = 0.5 * torch.sqrt(torch.abs(1 + torch.stack([\n",
    "            Rxx - Ryy - Rzz,\n",
    "            - Rxx + Ryy - Rzz,\n",
    "            - Rxx - Ryy + Rzz\n",
    "        ], -1)))\n",
    "        _R = lambda i, j: R[:, :, :, i, j]\n",
    "        signs = torch.sign(torch.stack([\n",
    "            _R(2, 1) - _R(1, 2),\n",
    "            _R(0, 2) - _R(2, 0),\n",
    "            _R(1, 0) - _R(0, 1)\n",
    "        ], -1))\n",
    "        xyz = signs * magnitudes\n",
    "        w = torch.sqrt(F.relu(1 + diag.sum(-1, keepdim=True))) / 2.\n",
    "        Q = torch.cat((xyz, w), -1)\n",
    "        Q = F.normalize(Q, dim=-1)\n",
    "        return Q\n",
    "\n",
    "    def _orientations_coarse(self, X, E_idx, eps=1e-6):\n",
    "        V = X.clone()\n",
    "        X = X[:, :, :6, :].reshape(X.shape[0], 6 * X.shape[1], 3)\n",
    "        dX = X[:, 1:, :] - X[:, :-1, :]\n",
    "        U = _normalize(dX, dim=-1)\n",
    "        u_0, u_1 = U[:, :-2, :], U[:, 1:-1, :]\n",
    "        n_0 = _normalize(torch.cross(u_0, u_1, dim=-1), dim=-1)\n",
    "        b_1 = _normalize(u_0 - u_1, dim=-1)\n",
    "\n",
    "        # select C3'\n",
    "        n_0 = n_0[:, 4::6, :]\n",
    "        b_1 = b_1[:, 4::6, :]\n",
    "        X = X[:, 4::6, :]\n",
    "        Q = torch.stack((b_1, n_0, torch.cross(b_1, n_0, dim=-1)), 2)\n",
    "        Q = Q.view(list(Q.shape[:2]) + [9])\n",
    "        Q = F.pad(Q, (0, 0, 0, 1), 'constant', 0)  # [16, 464, 9]\n",
    "\n",
    "        Q_neighbors = gather_nodes(Q, E_idx)  # [16, 464, 30, 9]\n",
    "        P_neighbors = gather_nodes(V[:, :, 0, :], E_idx)  # [16, 464, 30, 3]\n",
    "        O5_neighbors = gather_nodes(V[:, :, 1, :], E_idx)\n",
    "        C5_neighbors = gather_nodes(V[:, :, 2, :], E_idx)\n",
    "        C4_neighbors = gather_nodes(V[:, :, 3, :], E_idx)\n",
    "        O3_neighbors = gather_nodes(V[:, :, 5, :], E_idx)\n",
    "\n",
    "        Q = Q.view(list(Q.shape[:2]) + [3, 3]).unsqueeze(2)  # [16, 464, 1, 3, 3]\n",
    "        Q_neighbors = Q_neighbors.view(list(Q_neighbors.shape[:3]) + [3, 3])  # [16, 464, 30, 3, 3]\n",
    "\n",
    "        dX = torch.stack([P_neighbors, O5_neighbors, C5_neighbors, C4_neighbors, O3_neighbors], dim=3) - X[:, :, None,\n",
    "                                                                                                         None,\n",
    "                                                                                                         :]  # [16, 464, 30, 3]\n",
    "        dU = torch.matmul(Q[:, :, :, None, :, :], dX[..., None]).squeeze(-1)  # [16, 464, 30, 3] 邻居的相对坐标\n",
    "        B, N, K = dU.shape[:3]\n",
    "        E_direct = _normalize(dU, dim=-1)\n",
    "        E_direct = E_direct.reshape(B, N, K, -1)\n",
    "        R = torch.matmul(Q.transpose(-1, -2), Q_neighbors)\n",
    "        E_orient = self._quaternions(R)\n",
    "\n",
    "        dX_inner = V[:, :, [0, 2, 3], :] - X.unsqueeze(-2)\n",
    "        dU_inner = torch.matmul(Q, dX_inner.unsqueeze(-1)).squeeze(-1)\n",
    "        dU_inner = _normalize(dU_inner, dim=-1)\n",
    "        V_direct = dU_inner.reshape(B, N, -1)\n",
    "        return V_direct, E_direct, E_orient\n",
    "\n",
    "    def _dihedrals(self, X, eps=1e-7):\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        X = X[:, :, :6, :].reshape(X.shape[0], 6 * X.shape[1], 3)\n",
    "\n",
    "        # Shifted slices of unit vectors\n",
    "        # https://iupac.qmul.ac.uk/misc/pnuc2.html#220\n",
    "        # https://x3dna.org/highlights/torsion-angles-of-nucleic-acid-structures\n",
    "        # alpha:   O3'_{i-1} P_i O5'_i C5'_i\n",
    "        # beta:    P_i O5'_i C5'_i C4'_i\n",
    "        # gamma:   O5'_i C5'_i C4'_i C3'_i\n",
    "        # delta:   C5'_i C4'_i C3'_i O3'_i\n",
    "        # epsilon: C4'_i C3'_i O3'_i P_{i+1}\n",
    "        # zeta:    C3'_i O3'_i P_{i+1} O5'_{i+1}\n",
    "        # What's more:\n",
    "        #   chi: C1' - N9\n",
    "        #   chi is different for (C, T, U) and (A, G) https://x3dna.org/highlights/the-chi-x-torsion-angle-characterizes-base-sugar-relative-orientation\n",
    "\n",
    "        dX = X[:, 5:, :] - X[:, :-5, :]  # O3'-P, P-O5', O5'-C5', C5'-C4', ...\n",
    "        U = F.normalize(dX, dim=-1)\n",
    "        u_2 = U[:, :-2, :]  # O3'-P, P-O5', ...\n",
    "        u_1 = U[:, 1:-1, :]  # P-O5', O5'-C5', ...\n",
    "        u_0 = U[:, 2:, :]  # O5'-C5', C5'-C4', ...\n",
    "        # Backbone normals\n",
    "        n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)\n",
    "        n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)\n",
    "\n",
    "        # Angle between normals\n",
    "        cosD = (n_2 * n_1).sum(-1)\n",
    "        cosD = torch.clamp(cosD, -1 + eps, 1 - eps)\n",
    "        D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)\n",
    "        D = F.pad(D, (3, 4), 'constant', 0)\n",
    "        D = D.view((D.size(0), D.size(1) // 6, 6))\n",
    "        return torch.cat((torch.cos(D), torch.sin(D)), 2)  # return D_features\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        if self.training and self.augment_eps > 0:\n",
    "            X = X + self.augment_eps * torch.randn_like(X)\n",
    "\n",
    "        # Build k-Nearest Neighbors graph\n",
    "        B, N, _, _ = X.shape\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_dict = dict(zip(['P', 'O5_', 'C5_', 'C4_', 'C3_', 'O3_'], X.unbind(dim=2)))\n",
    "\n",
    "        X_backbone = atom_dict[\"P\"]\n",
    "        D_neighbors, E_idx = self._dist(X_backbone, mask)\n",
    "\n",
    "        mask_attend = gather_nodes(mask.unsqueeze(-1), E_idx).squeeze(-1)\n",
    "        mask_attend = (mask.unsqueeze(-1) * mask_attend) == 1\n",
    "        edge_mask_select = lambda x: torch.masked_select(x, mask_attend.unsqueeze(-1)).reshape(-1, x.shape[-1])\n",
    "        node_mask_select = lambda x: torch.masked_select(x, mask.bool().unsqueeze(-1)).reshape(-1, x.shape[-1])\n",
    "\n",
    "        # node features\n",
    "        h_V = []\n",
    "        # angle\n",
    "        V_angle = self._dihedrals(X)\n",
    "        V_angle = node_mask_select(V_angle)\n",
    "        # distance\n",
    "        node_list = ['O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        V_dist = []\n",
    "\n",
    "        for pair in node_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            V_dist.append(node_mask_select(\n",
    "                self._get_rbf__node(atom_dict[atom1], atom_dict[atom2]).squeeze()))\n",
    "        V_dist = torch.cat(tuple(V_dist), dim=-1).squeeze()\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        V_direct = node_mask_select(V_direct)\n",
    "        E_direct, E_orient = list(map(lambda x: edge_mask_select(x), [E_direct, E_orient]))\n",
    "\n",
    "        # edge features\n",
    "        h_E = []\n",
    "        # dist\n",
    "        edge_list = ['P-P', 'O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        E_dist = []\n",
    "        for pair in edge_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            E_dist.append(\n",
    "                edge_mask_select(self._get_rbf__edge(atom_dict[atom1], atom_dict[atom2], E_idx)))\n",
    "        E_dist = torch.cat(tuple(E_dist), dim=-1)\n",
    "\n",
    "        if 'angle' in self.node_feat_types:\n",
    "            h_V.append(V_angle)\n",
    "        if 'distance' in self.node_feat_types:\n",
    "            h_V.append(V_dist)\n",
    "        if 'direction' in self.node_feat_types:\n",
    "            h_V.append(V_direct)\n",
    "\n",
    "        if 'orientation' in self.edge_feat_types:\n",
    "            h_E.append(E_orient)\n",
    "        if 'distance' in self.edge_feat_types:\n",
    "            h_E.append(E_dist)\n",
    "        if 'direction' in self.edge_feat_types:\n",
    "            h_E.append(E_direct)\n",
    "\n",
    "        # Embed the nodes\n",
    "        h_V = self.norm_nodes(self.node_embedding(torch.cat(h_V, dim=-1)))\n",
    "        h_E = self.norm_edges(self.edge_embedding(torch.cat(h_E, dim=-1)))\n",
    "\n",
    "        # prepare the variables to return\n",
    "        shift = mask.sum(dim=1).cumsum(dim=0) - mask.sum(dim=1)\n",
    "        src = shift.view(B, 1, 1) + E_idx\n",
    "        src = torch.masked_select(src, mask_attend).view(1, -1)\n",
    "        dst = shift.view(B, 1, 1) + torch.arange(0, N, device=src.device).view(1, -1, 1).expand_as(mask_attend)\n",
    "        dst = torch.masked_select(dst, mask_attend).view(1, -1)\n",
    "        E_idx = torch.cat((dst, src), dim=0).long()\n",
    "\n",
    "        sparse_idx = mask.nonzero()\n",
    "        X = X[sparse_idx[:, 0], sparse_idx[:, 1], :, :]\n",
    "        batch_id = sparse_idx[:,0]\n",
    "        return h_V, h_E, E_idx, batch_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "81d99837",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 1])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.tensor([[1,2],[1,4]])\n",
    "mask_bool = a == 1\n",
    "S = torch.masked_select(a, mask_bool)\n",
    "S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "e12b215f-66ff-46cb-8645-733655cbf66f",
   "metadata": {},
   "outputs": [],
   "source": [
    "class RNAModel(nn.Module):\n",
    "    def __init__(self, model_config):\n",
    "        super(RNAModel, self).__init__()\n",
    "\n",
    "        self.smoothing = model_config.smoothing\n",
    "        self.node_features = self.edge_features = model_config.hidden\n",
    "        self.hidden_dim = model_config.hidden\n",
    "        self.vocab = model_config.vocab_size\n",
    "\n",
    "        \n",
    "        # self.features = RNAGraphBuilder(\n",
    "        #     model_config.hidden, model_config.hidden,\n",
    "        #     top_k=model_config.k_neighbors,\n",
    "        #     augment_eps=0.1  # 增加数据增强\n",
    "        # )\n",
    "        self.features = RNAFeatures(\n",
    "            model_config.hidden, model_config.hidden,\n",
    "            top_k=model_config.k_neighbors,\n",
    "            dropout=model_config.dropout,\n",
    "            node_feat_types=model_config.node_feat_types,\n",
    "            edge_feat_types=model_config.edge_feat_types,\n",
    "            augment_eps=0.1  # 增加数据增强\n",
    "        )\n",
    "\n",
    "        layer = MPNNLayer\n",
    "        self.W_s = nn.Embedding(model_config.vocab_size, self.hidden_dim)\n",
    "        self.encoder_layers = nn.ModuleList([\n",
    "            layer(self.hidden_dim, self.hidden_dim*2, dropout=model_config.dropout)\n",
    "            for _ in range(model_config.num_encoder_layers)])\n",
    "        self.decoder_layers = nn.ModuleList([\n",
    "            layer(self.hidden_dim, self.hidden_dim*2, dropout=model_config.dropout)\n",
    "            for _ in range(model_config.num_decoder_layers)])\n",
    "\n",
    "        self.projection_head = nn.Sequential(\n",
    "            nn.Linear(self.hidden_dim, self.hidden_dim, bias=False), \n",
    "            nn.ReLU(inplace=True), \n",
    "            nn.Linear(self.hidden_dim, self.hidden_dim, bias=True)\n",
    "        )\n",
    "        # 结点四分类\n",
    "        self.readout = nn.Linear(self.hidden_dim, model_config.vocab_size, bias=True)\n",
    "\n",
    "        # 更谨慎的初始化\n",
    "        self.init_weights()\n",
    "\n",
    "    def init_weights(self):\n",
    "        for p in self.parameters():\n",
    "            if p.dim() > 1:\n",
    "                if isinstance(p, nn.Linear):\n",
    "                    nn.init.xavier_uniform_(p, gain=nn.init.calculate_gain('gelu'))\n",
    "                elif isinstance(p, nn.LayerNorm):\n",
    "                    nn.init.constant_(p.weight, 1.0)\n",
    "                    nn.init.constant_(p.bias, 0.0)\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        # 抽取结点特征，边特征， 边索引，批次索引\n",
    "        h_V, h_E, E_idx, batch_id = self.features(X, mask)\n",
    "        \n",
    "        # 边特征保持不变，聚合边特征到结点\n",
    "        for enc_layer in self.encoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = enc_layer(h_V, h_EV, E_idx, batch_id)\n",
    "        # 边特征保持不变，再次聚合边特征到结点\n",
    "        for dec_layer in self.decoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = dec_layer(h_V, h_EV, E_idx, batch_id)\n",
    "\n",
    "        graph_embs = []\n",
    "        # 遍历每个样本\n",
    "        for b_id in range(batch_id[-1].item()+1):\n",
    "            # 求均值\n",
    "            b_data = h_V[batch_id == b_id].mean(0)\n",
    "            graph_embs.append(b_data)\n",
    "        graph_embs = torch.stack(graph_embs, dim=0)\n",
    "        # 全连接层\n",
    "        graph_prjs = self.projection_head(graph_embs)\n",
    "        # 碱基四分类器\n",
    "        logits = self.readout(h_V)\n",
    "        return logits, graph_prjs\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "6fce9f8d-d53a-48a1-a082-1047dca20c5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n"
     ]
    }
   ],
   "source": [
    "model = RNAModel(config.model_config).to(config.device)\n",
    "# print(model)\n",
    "print(model.training)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "528c5443",
   "metadata": {},
   "source": [
    "### training\n",
    "\n",
    "+ 怎么选择优化器和学习率\n",
    "\n",
    "    + 常用范围：0.001（Adam系）或 0.01（SGD）48。\n",
    "    + 小数据集调参：先用 0.01 测试，根据训练波动调整（波动大则降，收敛慢则升）\n",
    "\n",
    "```text\n",
    "新手：‌AdamW/Adam + 初始LR=3e-4 + 余弦退火‌\n",
    "老手：‌SGD+动量 + 多阶段LR衰减 + 梯度裁剪‌\n",
    "最终以验证集性能为 golden  standard\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "fa10ad13-dc08-4515-b2e0-3fe96bee7d0d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch import optim\n",
    "import torch.amp as amp\n",
    "from torch.optim.lr_scheduler import LambdaLR\n",
    "\n",
    "# 使用AdamW优化器\n",
    "optimizer = optim.AdamW(\n",
    "    model.parameters(),\n",
    "    lr=5e-4,\n",
    "    weight_decay=0.01  # 添加权重衰减\n",
    ")\n",
    "\n",
    "# 学习率调度器\n",
    "scheduler = optim.lr_scheduler.ReduceLROnPlateau(\n",
    "    optimizer, mode='min', factor=0.5, patience=3, verbose=True\n",
    ")  # 根据验证集的表现调整学习率，如果结果经过patience个epoch不改善就降低学习率\n",
    "\n",
    "\n",
    "# 在训练脚本中添加\n",
    "class LabelSmoothingLoss(nn.Module):\n",
    "    def __init__(self, classes=4, smoothing=0.2, ignore_index=-100):  # 增加平滑系数\n",
    "        super(LabelSmoothingLoss, self).__init__()\n",
    "        self.confidence = 1.0 - smoothing\n",
    "        self.smoothing = smoothing\n",
    "        self.classes = classes\n",
    "        self.ignore_index = ignore_index\n",
    "\n",
    "    def forward(self, pred, target):\n",
    "        pred = pred.log_softmax(dim=-1)\n",
    "        with torch.no_grad():\n",
    "            true_dist = torch.zeros_like(pred)\n",
    "            true_dist.fill_(self.smoothing / (self.classes - 1))\n",
    "            true_dist.scatter_(1, target.data.unsqueeze(1), self.confidence)\n",
    "        return torch.mean(torch.sum(-true_dist * pred, dim=-1))\n",
    "\n",
    "device = config.device\n",
    "scaler = amp.GradScaler(device)  # 混合精度训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "dac46261",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2610"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_config.epoch * len(train_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "2c96f610",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 1 [Train]:   0%|          | 0/261 [00:00<?, ?it/s]"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 1 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.37it/s, loss=1.36]\n",
      "Epoch 1 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 10.50it/s, recovery=0.375]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1: Train Loss=1.3733, Valid Loss=1.3446, Recovery=0.3370\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 2 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.73it/s, loss=1.33]\n",
      "Epoch 2 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.48it/s, recovery=0.396]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 2: Train Loss=1.3274, Valid Loss=1.3055, Recovery=0.3795\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 3 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.69it/s, loss=1.25]\n",
      "Epoch 3 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.44it/s, recovery=0.411]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 3: Train Loss=1.2839, Valid Loss=1.2492, Recovery=0.4091\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 4 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.49it/s, loss=1.13]\n",
      "Epoch 4 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.37it/s, recovery=0.401]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 4: Train Loss=1.2417, Valid Loss=1.2050, Recovery=0.4361\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 5 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.59it/s, loss=1.26]\n",
      "Epoch 5 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.29it/s, recovery=0.469]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 5: Train Loss=1.2035, Valid Loss=1.1760, Recovery=0.4488\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 6 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.44it/s, loss=1.07]\n",
      "Epoch 6 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.32it/s, recovery=0.464]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 6: Train Loss=1.1693, Valid Loss=1.1281, Recovery=0.4756\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 7 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=1.17] \n",
      "Epoch 7 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.28it/s, recovery=0.432]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 7: Train Loss=1.1458, Valid Loss=1.1328, Recovery=0.4755\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 8 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.38it/s, loss=1.3]  \n",
      "Epoch 8 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.26it/s, recovery=0.464]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 8: Train Loss=1.1259, Valid Loss=1.1132, Recovery=0.4875\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 9 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.45it/s, loss=1.29] \n",
      "Epoch 9 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.22it/s, recovery=0.458]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 9: Train Loss=1.1093, Valid Loss=1.0779, Recovery=0.4982\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 10 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=1.02] \n",
      "Epoch 10 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.18it/s, recovery=0.469]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 10: Train Loss=1.0873, Valid Loss=1.0660, Recovery=0.5019\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 11 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=1.21] \n",
      "Epoch 11 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.23it/s, recovery=0.495]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 11: Train Loss=1.0747, Valid Loss=1.0501, Recovery=0.5201\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 12 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.60it/s, loss=1.12] \n",
      "Epoch 12 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.17it/s, recovery=0.453]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 12: Train Loss=1.0621, Valid Loss=1.0474, Recovery=0.5203\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 13 [Train]: 100%|██████████| 261/261 [00:28<00:00,  9.29it/s, loss=1.03] \n",
      "Epoch 13 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.11it/s, recovery=0.453]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 13: Train Loss=1.0521, Valid Loss=1.0226, Recovery=0.5320\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 14 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.39it/s, loss=0.979]\n",
      "Epoch 14 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.22it/s, recovery=0.443]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 14: Train Loss=1.0295, Valid Loss=1.0421, Recovery=0.5167\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 15 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.52it/s, loss=1.08] \n",
      "Epoch 15 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.16it/s, recovery=0.479]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 15: Train Loss=1.0202, Valid Loss=1.0194, Recovery=0.5335\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 16 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.51it/s, loss=1.4]  \n",
      "Epoch 16 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.10it/s, recovery=0.396]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 16: Train Loss=1.0244, Valid Loss=1.0208, Recovery=0.5317\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 17 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=1.28] \n",
      "Epoch 17 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.10it/s, recovery=0.406]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 17: Train Loss=1.0141, Valid Loss=1.0115, Recovery=0.5430\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 18 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.56it/s, loss=1.11] \n",
      "Epoch 18 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.12it/s, recovery=0.458]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 18: Train Loss=1.0064, Valid Loss=1.0078, Recovery=0.5552\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 19 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.34it/s, loss=0.935]\n",
      "Epoch 19 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.20it/s, recovery=0.516]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 19: Train Loss=1.0001, Valid Loss=1.0068, Recovery=0.5458\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 20 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=0.895]\n",
      "Epoch 20 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.09it/s, recovery=0.464]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 20: Train Loss=0.9957, Valid Loss=0.9886, Recovery=0.5546\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 21 [Train]: 100%|██████████| 261/261 [00:28<00:00,  9.31it/s, loss=0.978]\n",
      "Epoch 21 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.20it/s, recovery=0.448]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 21: Train Loss=0.9849, Valid Loss=0.9893, Recovery=0.5488\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 22 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.48it/s, loss=1.15] \n",
      "Epoch 22 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.16it/s, recovery=0.458]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 22: Train Loss=0.9889, Valid Loss=0.9804, Recovery=0.5607\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 23 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.43it/s, loss=1.11] \n",
      "Epoch 23 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.10it/s, recovery=0.49] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 23: Train Loss=0.9708, Valid Loss=0.9794, Recovery=0.5653\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 24 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=0.978]\n",
      "Epoch 24 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.04it/s, recovery=0.505]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 24: Train Loss=0.9721, Valid Loss=0.9687, Recovery=0.5739\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 25 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.51it/s, loss=1.12] \n",
      "Epoch 25 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.05it/s, recovery=0.49] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 25: Train Loss=0.9637, Valid Loss=0.9670, Recovery=0.5667\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 26 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.49it/s, loss=1.13] \n",
      "Epoch 26 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.20it/s, recovery=0.49] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 26: Train Loss=0.9621, Valid Loss=0.9684, Recovery=0.5669\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 27 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.39it/s, loss=1.14] \n",
      "Epoch 27 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.05it/s, recovery=0.464]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 27: Train Loss=0.9617, Valid Loss=0.9691, Recovery=0.5662\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 28 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.53it/s, loss=0.966]\n",
      "Epoch 28 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.22it/s, recovery=0.526]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 28: Train Loss=0.9625, Valid Loss=0.9661, Recovery=0.5649\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 29 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.37it/s, loss=0.979]\n",
      "Epoch 29 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.19it/s, recovery=0.505]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 29: Train Loss=0.9451, Valid Loss=0.9611, Recovery=0.5782\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 30 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.33it/s, loss=1.19] \n",
      "Epoch 30 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.17it/s, recovery=0.5]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 30: Train Loss=0.9511, Valid Loss=0.9517, Recovery=0.5819\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 31 [Train]: 100%|██████████| 261/261 [00:28<00:00,  9.23it/s, loss=0.81] \n",
      "Epoch 31 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.17it/s, recovery=0.484]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 31: Train Loss=0.9414, Valid Loss=0.9629, Recovery=0.5729\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 32 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.53it/s, loss=1.16] \n",
      "Epoch 32 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.09it/s, recovery=0.552]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 32: Train Loss=0.9467, Valid Loss=0.9497, Recovery=0.5807\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 33 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.45it/s, loss=1.16] \n",
      "Epoch 33 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.12it/s, recovery=0.484]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 33: Train Loss=0.9385, Valid Loss=0.9503, Recovery=0.5798\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 34 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.39it/s, loss=0.932]\n",
      "Epoch 34 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.18it/s, recovery=0.49] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 34: Train Loss=0.9319, Valid Loss=0.9415, Recovery=0.5932\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 35 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.44it/s, loss=0.83] \n",
      "Epoch 35 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.05it/s, recovery=0.484]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 35: Train Loss=0.9374, Valid Loss=0.9399, Recovery=0.5951\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 36 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.61it/s, loss=0.802]\n",
      "Epoch 36 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 10.99it/s, recovery=0.464]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 36: Train Loss=0.9401, Valid Loss=0.9506, Recovery=0.5905\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 37 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.53it/s, loss=0.971]\n",
      "Epoch 37 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.07it/s, recovery=0.51] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 37: Train Loss=0.9314, Valid Loss=0.9396, Recovery=0.5929\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 38 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.45it/s, loss=1.06] \n",
      "Epoch 38 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.04it/s, recovery=0.552]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 38: Train Loss=0.9254, Valid Loss=0.9367, Recovery=0.5913\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 39 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.49it/s, loss=1]    \n",
      "Epoch 39 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.12it/s, recovery=0.474]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 39: Train Loss=0.9270, Valid Loss=0.9339, Recovery=0.5996\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 40 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=1.28] \n",
      "Epoch 40 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.13it/s, recovery=0.531]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 40: Train Loss=0.9203, Valid Loss=0.9297, Recovery=0.5990\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 41 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.58it/s, loss=0.857]\n",
      "Epoch 41 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 10.92it/s, recovery=0.474]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 41: Train Loss=0.9232, Valid Loss=0.9400, Recovery=0.5999\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 42 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.37it/s, loss=0.815]\n",
      "Epoch 42 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.21it/s, recovery=0.557]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 42: Train Loss=0.9159, Valid Loss=0.9352, Recovery=0.5959\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 43 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=1.02] \n",
      "Epoch 43 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.13it/s, recovery=0.521]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 43: Train Loss=0.9203, Valid Loss=0.9370, Recovery=0.6069\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 44 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=0.924]\n",
      "Epoch 44 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.02it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 44: Train Loss=0.9158, Valid Loss=0.9326, Recovery=0.6043\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 45 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.56it/s, loss=0.915]\n",
      "Epoch 45 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.27it/s, recovery=0.573]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 45: Train Loss=0.8990, Valid Loss=0.9290, Recovery=0.6064\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 46 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.35it/s, loss=0.976]\n",
      "Epoch 46 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.24it/s, recovery=0.562]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 46: Train Loss=0.8945, Valid Loss=0.9208, Recovery=0.6094\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 47 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.49it/s, loss=0.801]\n",
      "Epoch 47 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.13it/s, recovery=0.542]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 47: Train Loss=0.8939, Valid Loss=0.9199, Recovery=0.6165\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 48 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.68it/s, loss=0.893]\n",
      "Epoch 48 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.13it/s, recovery=0.495]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 48: Train Loss=0.8927, Valid Loss=0.9234, Recovery=0.6159\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 49 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.57it/s, loss=0.797]\n",
      "Epoch 49 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.15it/s, recovery=0.542]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 49: Train Loss=0.8835, Valid Loss=0.9194, Recovery=0.6152\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 50 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.89it/s, loss=0.976]\n",
      "Epoch 50 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.16it/s, recovery=0.547]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 50: Train Loss=0.8760, Valid Loss=0.9201, Recovery=0.6168\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 51 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.58it/s, loss=0.849]\n",
      "Epoch 51 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.08it/s, recovery=0.547]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 51: Train Loss=0.8865, Valid Loss=0.9169, Recovery=0.6216\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 52 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.48it/s, loss=0.762]\n",
      "Epoch 52 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.08it/s, recovery=0.552]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 52: Train Loss=0.8838, Valid Loss=0.9140, Recovery=0.6191\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 53 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.62it/s, loss=0.789]\n",
      "Epoch 53 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.12it/s, recovery=0.568]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 53: Train Loss=0.8734, Valid Loss=0.9185, Recovery=0.6185\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 54 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.85it/s, loss=1.13] \n",
      "Epoch 54 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.13it/s, recovery=0.562]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 54: Train Loss=0.8821, Valid Loss=0.9167, Recovery=0.6188\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 55 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.60it/s, loss=0.807]\n",
      "Epoch 55 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.14it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 55: Train Loss=0.8746, Valid Loss=0.9218, Recovery=0.6100\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 56 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.50it/s, loss=1.12] \n",
      "Epoch 56 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.15it/s, recovery=0.578]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 56: Train Loss=0.8788, Valid Loss=0.9176, Recovery=0.6164\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 57 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.50it/s, loss=0.764]\n",
      "Epoch 57 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.12it/s, recovery=0.573]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 57: Train Loss=0.8682, Valid Loss=0.9131, Recovery=0.6213\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 58 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.46it/s, loss=0.8]  \n",
      "Epoch 58 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.15it/s, recovery=0.573]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 58: Train Loss=0.8663, Valid Loss=0.9103, Recovery=0.6240\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 59 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.44it/s, loss=1.06] \n",
      "Epoch 59 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.07it/s, recovery=0.568]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 59: Train Loss=0.8597, Valid Loss=0.9090, Recovery=0.6262\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 60 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.71it/s, loss=0.934]\n",
      "Epoch 60 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.18it/s, recovery=0.583]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 60: Train Loss=0.8580, Valid Loss=0.9135, Recovery=0.6261\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 61 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.76it/s, loss=0.812]\n",
      "Epoch 61 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.22it/s, recovery=0.536]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 61: Train Loss=0.8639, Valid Loss=0.9111, Recovery=0.6203\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 62 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.78it/s, loss=0.885]\n",
      "Epoch 62 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.03it/s, recovery=0.562]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 62: Train Loss=0.8605, Valid Loss=0.9116, Recovery=0.6189\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 63 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.77it/s, loss=0.8]  \n",
      "Epoch 63 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.21it/s, recovery=0.531]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 63: Train Loss=0.8580, Valid Loss=0.9095, Recovery=0.6240\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 64 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.76it/s, loss=0.749]\n",
      "Epoch 64 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.19it/s, recovery=0.531]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 64: Train Loss=0.8516, Valid Loss=0.9069, Recovery=0.6329\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 65 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.79it/s, loss=0.952]\n",
      "Epoch 65 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.25it/s, recovery=0.547]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 65: Train Loss=0.8527, Valid Loss=0.9074, Recovery=0.6261\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 66 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.79it/s, loss=0.861]\n",
      "Epoch 66 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.14it/s, recovery=0.578]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 66: Train Loss=0.8541, Valid Loss=0.9065, Recovery=0.6292\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 67 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.66it/s, loss=0.783]\n",
      "Epoch 67 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.06it/s, recovery=0.578]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 67: Train Loss=0.8555, Valid Loss=0.9097, Recovery=0.6282\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 68 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.73it/s, loss=0.819]\n",
      "Epoch 68 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.15it/s, recovery=0.536]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 68: Train Loss=0.8520, Valid Loss=0.9107, Recovery=0.6321\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 69 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.55it/s, loss=0.779]\n",
      "Epoch 69 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.24it/s, recovery=0.547]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 69: Train Loss=0.8542, Valid Loss=0.9085, Recovery=0.6295\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 70 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.55it/s, loss=0.853]\n",
      "Epoch 70 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.27it/s, recovery=0.552]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 70: Train Loss=0.8523, Valid Loss=0.9074, Recovery=0.6263\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 71 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.48it/s, loss=0.755]\n",
      "Epoch 71 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.29it/s, recovery=0.552]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 71: Train Loss=0.8464, Valid Loss=0.9078, Recovery=0.6271\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 72 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.59it/s, loss=0.985]\n",
      "Epoch 72 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.30it/s, recovery=0.562]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 72: Train Loss=0.8468, Valid Loss=0.9077, Recovery=0.6305\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 73 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.67it/s, loss=0.746]\n",
      "Epoch 73 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.29it/s, recovery=0.557]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 73: Train Loss=0.8468, Valid Loss=0.9067, Recovery=0.6352\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 74 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.46it/s, loss=1.04] \n",
      "Epoch 74 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.24it/s, recovery=0.568]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 74: Train Loss=0.8510, Valid Loss=0.9058, Recovery=0.6308\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 75 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.58it/s, loss=1.03] \n",
      "Epoch 75 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.28it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 75: Train Loss=0.8469, Valid Loss=0.9056, Recovery=0.6309\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 76 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.69it/s, loss=0.949]\n",
      "Epoch 76 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.32it/s, recovery=0.604]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 76: Train Loss=0.8483, Valid Loss=0.9074, Recovery=0.6278\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 77 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.71it/s, loss=0.814]\n",
      "Epoch 77 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.31it/s, recovery=0.573]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 77: Train Loss=0.8482, Valid Loss=0.9062, Recovery=0.6304\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 78 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.63it/s, loss=0.935]\n",
      "Epoch 78 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.15it/s, recovery=0.583]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 78: Train Loss=0.8474, Valid Loss=0.9056, Recovery=0.6311\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 79 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.59it/s, loss=0.824]\n",
      "Epoch 79 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.34it/s, recovery=0.604]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 79: Train Loss=0.8431, Valid Loss=0.9063, Recovery=0.6308\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 80 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.54it/s, loss=0.85] \n",
      "Epoch 80 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.25it/s, recovery=0.568]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 80: Train Loss=0.8473, Valid Loss=0.9062, Recovery=0.6309\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 81 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.61it/s, loss=0.836]\n",
      "Epoch 81 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.35it/s, recovery=0.578]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 81: Train Loss=0.8445, Valid Loss=0.9065, Recovery=0.6297\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 82 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.59it/s, loss=0.876]\n",
      "Epoch 82 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.34it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 82: Train Loss=0.8454, Valid Loss=0.9067, Recovery=0.6284\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 83 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.64it/s, loss=0.781]\n",
      "Epoch 83 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.35it/s, recovery=0.573]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 83: Train Loss=0.8412, Valid Loss=0.9056, Recovery=0.6307\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 84 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.69it/s, loss=0.875]\n",
      "Epoch 84 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.36it/s, recovery=0.578]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 84: Train Loss=0.8460, Valid Loss=0.9062, Recovery=0.6268\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 85 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.67it/s, loss=0.845]\n",
      "Epoch 85 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.34it/s, recovery=0.568]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 85: Train Loss=0.8467, Valid Loss=0.9060, Recovery=0.6308\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 86 [Train]: 100%|██████████| 261/261 [00:26<00:00,  9.68it/s, loss=1.11] \n",
      "Epoch 86 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.36it/s, recovery=0.583]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 86: Train Loss=0.8472, Valid Loss=0.9060, Recovery=0.6304\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 87 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.53it/s, loss=0.986]\n",
      "Epoch 87 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.35it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 87: Train Loss=0.8443, Valid Loss=0.9062, Recovery=0.6295\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 88 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.42it/s, loss=1.18] \n",
      "Epoch 88 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.37it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 88: Train Loss=0.8509, Valid Loss=0.9055, Recovery=0.6308\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 89 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=0.781]\n",
      "Epoch 89 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.36it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 89: Train Loss=0.8434, Valid Loss=0.9060, Recovery=0.6298\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 90 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.49it/s, loss=0.756]\n",
      "Epoch 90 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.33it/s, recovery=0.599]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 90: Train Loss=0.8397, Valid Loss=0.9060, Recovery=0.6306\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 91 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=0.746]\n",
      "Epoch 91 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.34it/s, recovery=0.583]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 91: Train Loss=0.8472, Valid Loss=0.9059, Recovery=0.6301\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 92 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.59it/s, loss=0.767]\n",
      "Epoch 92 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.32it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 92: Train Loss=0.8478, Valid Loss=0.9057, Recovery=0.6296\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 93 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.57it/s, loss=0.741]\n",
      "Epoch 93 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.35it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 93: Train Loss=0.8419, Valid Loss=0.9058, Recovery=0.6295\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 94 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.52it/s, loss=0.883]\n",
      "Epoch 94 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.33it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 94: Train Loss=0.8455, Valid Loss=0.9061, Recovery=0.6296\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 95 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.51it/s, loss=0.839]\n",
      "Epoch 95 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.35it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 95: Train Loss=0.8431, Valid Loss=0.9061, Recovery=0.6303\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 96 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.47it/s, loss=0.761]\n",
      "Epoch 96 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.36it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 96: Train Loss=0.8415, Valid Loss=0.9061, Recovery=0.6300\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 97 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.56it/s, loss=0.816]\n",
      "Epoch 97 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.34it/s, recovery=0.589]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 97: Train Loss=0.8405, Valid Loss=0.9060, Recovery=0.6299\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 98 [Train]: 100%|██████████| 261/261 [00:27<00:00,  9.40it/s, loss=0.909]\n",
      "Epoch 98 [Valid]: 100%|██████████| 29/29 [00:02<00:00, 11.37it/s, recovery=0.594]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 98: Train Loss=0.8469, Valid Loss=0.9059, Recovery=0.6298\n",
      "Early stopping at epoch 98\n"
     ]
    }
   ],
   "source": [
    "# 训练循环\n",
    "best_valid_loss = 10000\n",
    "num_epoch_no_improve = 0\n",
    "max_patience = 10\n",
    "train_logs = []\n",
    "\n",
    "criterion = LabelSmoothingLoss()\n",
    "for epoch in range(1, 300):  # 最大100个epoch\n",
    "    # 训练阶段\n",
    "    model.train()\n",
    "    epoch_loss = 0\n",
    "    train_pbar = tqdm(train_loader, desc=f'Epoch {epoch} [Train]')\n",
    "    \n",
    "    for batch in train_pbar:\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(device, non_blocking=True)\n",
    "        S = S.to(device, non_blocking=True)\n",
    "        mask = mask.to(device, non_blocking=True)\n",
    "        # print(X.shape)\n",
    "        # print(S.shape)\n",
    "        # print(mask.shape)\n",
    "        S_masked = torch.masked_select(S, (mask == 1))\n",
    "        # print(S_masked.shape)\n",
    "        optimizer.zero_grad()\n",
    "        \n",
    "        # 混合精度训练\n",
    "        with amp.autocast(device):\n",
    "            logits, _  = model(X, mask)\n",
    "            # print(logits.shape)\n",
    "            loss = criterion(logits, S_masked)\n",
    "        \n",
    "        scaler.scale(loss).backward()\n",
    "        scaler.step(optimizer)\n",
    "        scaler.update()\n",
    "        \n",
    "        epoch_loss += loss.item()\n",
    "        train_pbar.set_postfix({'loss': loss.item()})\n",
    "\n",
    "    epoch_loss /= len(train_loader)\n",
    "    \n",
    "    # 验证阶段\n",
    "    model.eval()\n",
    "    valid_loss = 0\n",
    "    recovery_list = []\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        valid_pbar = tqdm(valid_loader, desc=f'Epoch {epoch} [Valid]')\n",
    "        for batch in valid_pbar:\n",
    "            X, S, mask, lengths, names = batch\n",
    "            X = X.to(device, non_blocking=True)\n",
    "            S = S.to(device, non_blocking=True)\n",
    "            mask = mask.to(device, non_blocking=True)\n",
    "            S_masked = torch.masked_select(S, (mask == 1))\n",
    "            logits, _ = model(X, mask)\n",
    "            loss = criterion(logits, S_masked)\n",
    "            valid_loss += loss.item()\n",
    "            ###############################\n",
    "            # preds = F.softmax(logits, dim=-1).argmax(dim=-1)\n",
    "            ###############################\n",
    "            preds = logits.argmax(dim=-1)\n",
    "            \n",
    "            # recovery = torch.eq(preds, S_masked).float().mean().item()\n",
    "            # recovery_list.append(recovery)\n",
    "            start_idx = 0\n",
    "            for length in lengths:\n",
    "                end_idx = start_idx + length.item()\n",
    "                pred = preds[start_idx: end_idx]\n",
    "                gt_S = S_masked[start_idx: end_idx]\n",
    "                recovery = torch.eq(pred, gt_S).float().mean().item()\n",
    "                recovery_list.append(recovery)\n",
    "                start_idx = end_idx\n",
    "            \n",
    "            valid_pbar.set_postfix({'recovery': recovery})\n",
    "\n",
    "    valid_loss /= len(valid_loader)\n",
    "    valid_recovery = np.mean(recovery_list)\n",
    "    \n",
    "    # 记录日志\n",
    "    train_logs.append((epoch_loss, valid_loss, valid_recovery))\n",
    "    print(f'Epoch {epoch}: Train Loss={epoch_loss:.4f}, Valid Loss={valid_loss:.4f}, Recovery={valid_recovery:.4f}')\n",
    "    \n",
    "    # 保存模型\n",
    "    torch.save(model.state_dict(), f'./weights/epoch_{epoch}.pt')\n",
    "    \n",
    "    # 学习率调整\n",
    "    scheduler.step(valid_loss)\n",
    "    # 早停\n",
    "    if valid_loss < best_valid_loss:\n",
    "        best_valid_loss = valid_loss\n",
    "        num_epoch_no_improve = 0\n",
    "        torch.save(model.state_dict(), 'best.pt')\n",
    "    else:\n",
    "        num_epoch_no_improve += 1\n",
    "        if num_epoch_no_improve >= max_patience:\n",
    "            print(f'Early stopping at epoch {epoch}')\n",
    "            break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "289b78b0",
   "metadata": {},
   "source": [
    "## 序列交叉熵示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "c8fff2cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "序列交叉熵损失: 1.4258\n"
     ]
    }
   ],
   "source": [
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "\n",
    "# 模拟数据\n",
    "logits = torch.tensor([[[1.2, 3.0, -0.5, 0.1], [0.5, 2.1, -1.0, 0.3], [0.1, -0.5, 1.5, 2.0]]])\n",
    "labels = torch.tensor([[1, 2, 3]])  # 目标词索引\n",
    "mask = torch.tensor([[1, 1, 1]])    # 有效位置掩码（无<PAD>）\n",
    "\n",
    "# 计算损失\n",
    "criterion = nn.CrossEntropyLoss(ignore_index=0, reduction='none')  # 忽略<PAD>\n",
    "loss = criterion(logits.view(-1, 4), labels.view(-1)) * mask.view(-1)\n",
    "final_loss = loss.sum() / mask.sum()  # 按有效位置平均\n",
    "print(f\"序列交叉熵损失: {final_loss.item():.4f}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "9af13790",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.765625e-07\n"
     ]
    }
   ],
   "source": [
    "import torch.optim as optim\n",
    " \n",
    "\n",
    "# 查看所有参数组的学习率\n",
    "for param_group in optimizer.param_groups:\n",
    "    print(param_group['lr'])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2122bf1d",
   "metadata": {},
   "source": [
    "### 显存不足报错\n",
    "\n",
    "RuntimeError: CUDA error: an illegal memory access was encountered\n",
    "CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.\n",
    "For debugging consider passing CUDA_LAUNCH_BLOCKING=1.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "beac3fe1",
   "metadata": {},
   "source": [
    "### test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "086fc510",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loading checkpoint from path: /workspace/sais_medicine/code/weights/best.pt\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "RNAModel(\n",
       "  (features): RNAFeatures(\n",
       "    (dropout): Dropout(p=0.1, inplace=False)\n",
       "    (node_embedding): Linear(in_features=101, out_features=128, bias=True)\n",
       "    (edge_embedding): Linear(in_features=115, out_features=128, bias=True)\n",
       "    (norm_nodes): Normalize()\n",
       "    (norm_edges): Normalize()\n",
       "  )\n",
       "  (W_s): Embedding(4, 128)\n",
       "  (encoder_layers): ModuleList(\n",
       "    (0-2): 3 x MPNNLayer(\n",
       "      (dropout): Dropout(p=0.1, inplace=False)\n",
       "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
       "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
       "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
       "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
       "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
       "      (act): ReLU()\n",
       "      (dense): Sequential(\n",
       "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
       "        (1): ReLU()\n",
       "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
       "      )\n",
       "    )\n",
       "  )\n",
       "  (decoder_layers): ModuleList(\n",
       "    (0-2): 3 x MPNNLayer(\n",
       "      (dropout): Dropout(p=0.1, inplace=False)\n",
       "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
       "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
       "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
       "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
       "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
       "      (act): ReLU()\n",
       "      (dense): Sequential(\n",
       "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
       "        (1): ReLU()\n",
       "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
       "      )\n",
       "    )\n",
       "  )\n",
       "  (projection_head): Sequential(\n",
       "    (0): Linear(in_features=128, out_features=128, bias=False)\n",
       "    (1): ReLU(inplace=True)\n",
       "    (2): Linear(in_features=128, out_features=128, bias=True)\n",
       "  )\n",
       "  (readout): Linear(in_features=128, out_features=4, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eval_model = RNAModel(config.model_config).to(config.device)\n",
    "checkpoint_path = train_config.ckpt_path\n",
    "print(\"loading checkpoint from path:\", checkpoint_path)\n",
    "eval_model.load_state_dict(torch.load(checkpoint_path, map_location='cpu', weights_only=True), strict=True)\n",
    "eval_model.to(config.device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "10158a05-4192-4f93-b173-a7ba4dc25a96",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 29/29 [00:02<00:00, 11.57it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "test recovery: 0.6729\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "recovery_list = []\n",
    "eval_model.eval()\n",
    "with torch.no_grad():\n",
    "    result_list = []\n",
    "    for batch in tqdm(valid_loader):\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(config.device)\n",
    "        S = S.to(config.device)\n",
    "        mask = mask.to(config.device)\n",
    "        logits, _ = eval_model(X, mask)\n",
    "        S = torch.masked_select(S, (mask==1))  # 选择有效的标签\n",
    "        probs = F.softmax(logits, dim=-1)\n",
    "        samples = probs.argmax(dim=-1)\n",
    "        start_idx = 0\n",
    "        for length in lengths:\n",
    "            end_idx = start_idx + length.item()\n",
    "            sample = samples[start_idx: end_idx]\n",
    "            result_list.append(sample)\n",
    "            gt_S = S[start_idx: end_idx]\n",
    "            recovery = (sample==gt_S).sum() / len(sample)\n",
    "            recovery_list.append(recovery.cpu().numpy())\n",
    "            start_idx = end_idx\n",
    "    test_recovery = np.mean(recovery_list)\n",
    "    print('test recovery: {:.4f}'.format(test_recovery))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b00ce785",
   "metadata": {},
   "source": [
    "### Predict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "4ea01db1",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2822485/2606622828.py:6: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.\n",
      "  state_dict = torch.load(ckpt, map_location=Config.device)\n",
      "100%|██████████| 29/29 [00:02<00:00, 11.30it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Valid Loss=1.5449, Recovery=0.8403, Recovery_seq=0.6729\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "model = RNAModel(config.model_config).to(Config.device)\n",
    "# 加载模型权重\n",
    "ckpt = train_config.ckpt_path\n",
    "ckpt = '/workspace/sais_medicine/code/weights_4/best.pt'  # train: 0.6816 valid_seq: 0.6729 val_token: 0.8403\n",
    "# ckpt = '/workspace/sais_medicine/code/weights_4/last.pt' # train: 0.6895 valid: 0.6654\n",
    "state_dict = torch.load(ckpt, map_location=Config.device)\n",
    "model.load_state_dict(state_dict)\n",
    "\n",
    "recovery_list = []\n",
    "recovery_list_seq = []\n",
    "model.eval()\n",
    "criterion = LabelSmoothingLoss()\n",
    "valid_loss = 0\n",
    "with torch.no_grad():\n",
    "    for batch in tqdm(valid_loader):\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(device, non_blocking=True)\n",
    "        S = S.to(device, non_blocking=True)\n",
    "        mask = mask.to(device, non_blocking=True)\n",
    "\n",
    "        logits, _ = model(X, mask)\n",
    "        S = torch.masked_select(S, (mask==1))  # 选择有效的标签\n",
    "        loss = criterion(logits, S)\n",
    "        valid_loss += loss.item()\n",
    "        \n",
    "        preds = logits.argmax(dim=-1)\n",
    "        recovery = torch.eq(preds, S).float().mean().item()\n",
    "        recovery_list.append(recovery)\n",
    "        \n",
    "        recovery = torch.eq(preds, S).float().mean().item()\n",
    "        recovery_list.append(recovery)\n",
    "\n",
    "        start_idx = 0\n",
    "        for length in lengths:\n",
    "            end_idx = start_idx + length.item()\n",
    "            sample = preds[start_idx: end_idx]\n",
    "            gt_S = S[start_idx: end_idx]\n",
    "            recovery = (sample==gt_S).sum() / len(sample)\n",
    "            recovery_list_seq.append(recovery.cpu().numpy())\n",
    "            start_idx = end_idx\n",
    "\n",
    "valid_loss /= len(valid_loader)\n",
    "valid_recovery = np.mean(recovery_list)\n",
    "valid_recovery_seq = np.mean(recovery_list_seq)\n",
    "\n",
    "# 记录日志\n",
    "print(f'Valid Loss={valid_loss:.4f}, Recovery={valid_recovery:.4f}, Recovery_seq={valid_recovery_seq:.4f}')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
